//批量替换文件名相同文字和批量追加文件名前缀
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

//初始化成功和失败的次数
var successNum, errorNum int = 0, 0

func main() {
	var (
		//初始化菜单按钮
		menuNum int
	)
	//获取真实路径
	dirPath, _ := os.Getwd()
	//把需要替换的所有文件都放在files这个目录下进行操作
	dirPath += "/files/"
	fmt.Println("***请把需要操作的所有文件，放在 files 文件夹下，没有的请新建一个files文件夹，执行程序.ext 和 files 文件夹是同级关系***")
	for {
		fmt.Println("\n======请选择功能======")
		fmt.Println("1.批量替换文件名相同文字\n2.批量添加文件名前缀\n3.退出")
		fmt.Print("请输入菜单数字：")
		//监听键盘输入
		fmt.Scanln(&menuNum)
		switch menuNum {
		case 1:
			//初始化 需要替换的文字和新的文字 变量
			var srcTitle, dscTitle string
			//重置成功次数，防止运行多次一直累积
			successNum = 0
			//重置失败次数，防止运行多次一直累积
			errorNum = 0

			fmt.Println("===文件名批量替换同文字 Ctrl+C 可提前终止程序===")
			fmt.Print("请输入需要替换的文字：")
			//监听输入
			fmt.Scanln(&srcTitle)
			fmt.Print("请输入新文字：")
			//监听输入
			fmt.Scanln(&dscTitle)
			fmt.Println("正在替换中，请稍后...")
			//开始执行文件名替换
			repeatTitle(srcTitle, dscTitle, dirPath)
			fmt.Printf("成功更新%d个文件，未更新%d个文件！\n", successNum, errorNum)
		case 2:
			//初始化前缀变量
			var prefixStr string
			//重置成功次数，防止运行多次一直累积
			successNum = 0
			//重置失败次数，防止运行多次一直累积
			errorNum = 0
			fmt.Println("===文件名批量追加前缀 Ctrl+C 可提前终止程序===")
			fmt.Print("请输入前缀文字：")
			//监听输入
			fmt.Scanln(&prefixStr)
			//开始追加文件名的前缀
			addPrefix(prefixStr, dirPath)
			fmt.Printf("\n成功追加%d个文件，未追加%d个文件！\n", successNum, errorNum)
		case 3:
			fmt.Println("我们下次再见~")
			os.Exit(-1)
		default:
			fmt.Println("请输入正确的菜单编号！\n")
		}
	}
}

//替换文件中指定的字符串
//srcTitle 需要替换的文字
//dscTitle 更新的文字
//dir 更新的文件夹
func repeatTitle(srcTitle, dscTitle, dir string) {
	//读取文件夹
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		fmt.Println("读取文件夹失败：", err)
		return
	}
	//遍历文件夹内的文件
	for _, file := range fs {
		//如果当前是文件夹，继续递归调用自身，实现无限文件夹的文件替换
		if file.IsDir() == true {
			repeatTitle(srcTitle, dscTitle, dir+file.Name()+"/")
		}
		//获取文件的名称
		fileName := file.Name()
		//判断文件名是否存在过需要替换的文字前缀
		if strings.Index(fileName, srcTitle) < 0 {
			continue
		}
		//新的文件名称
		newName := strings.Replace(fileName, srcTitle, dscTitle, 1)
		//旧的文件真实路径
		oldFile := dir + "/" + fileName
		//新的文件真实路径
		newFile := dir + "/" + newName
		//开始重命名文件名
		err := os.Rename(oldFile, newFile)
		if err != nil {
			//错误的次数统计
			errorNum++
		} else {
			//成功的次数统计
			successNum++
		}

	}
}

//批量给文件追加前缀
//prefix 前缀文字
//dir 追加文件的目录
func addPrefix(prefix, dir string) {
	//读取文件夹
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		fmt.Println("读取文件夹失败：", err)
		return
	}
	//遍历文件夹内的文件
	for _, file := range fs {
		//如果当前是文件夹，继续递归调用自身，实现无限文件夹的文件追加
		if file.IsDir() == true {
			addPrefix(prefix, dir+file.Name()+"/")
		} else {
			//获取文件名
			fileName := file.Name()
			//如果文件名已经存在了相同的前缀，则跳过
			if strings.Index(fileName, prefix) == 0 {
				continue
			}
			//新的文件名，新增了前缀
			newName := prefix + fileName
			//旧的文件
			oldFile := dir + "/" + fileName
			//新文件
			newFile := dir + "/" + newName
			//重命名文件
			err := os.Rename(oldFile, newFile)
			if err != nil {
				//错误的次数统计
				errorNum++
			} else {
				//成功的次数统计
				successNum++
			}
		}
	}
}
